package com.cmwa.scbp.utils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class RSASignature {
	private static Logger logger = LoggerFactory.getLogger(RSASignature.class);

	/**
	 * 签名算法
	 */
	public static final String SIGN_ALGORITHMS = "SHA1WithRSA";

	private static final String PUBLIC_KEY_PATH = "/pms/publicKeyFile";

	/*
	 * 创建秘钥对
	 */
	public static void genKeyPair(String privateKeyFilePath, String publicKeyFilePath) {
		KeyPairGenerator keyPairGen = null;
		try {
			keyPairGen = KeyPairGenerator.getInstance("RSA");
		} catch (NoSuchAlgorithmException e) {
			logger.error(e.getMessage());
		}
		keyPairGen.initialize(1024, new SecureRandom());
		KeyPair keyPair = keyPairGen.generateKeyPair();
		RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
		RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
		try {
			String publicKeyString = new Base64().encodeToString(publicKey.getEncoded());
			FileWriter pubfw = new FileWriter(publicKeyFilePath);
			BufferedWriter pubbw = new BufferedWriter(pubfw);
			pubbw.write(publicKeyString);
			pubbw.flush();
			pubbw.close();
			pubfw.close();

			String privateKeyString = new Base64().encodeToString(privateKey.getEncoded());
			FileWriter prifw = new FileWriter(privateKeyFilePath);
			BufferedWriter pribw = new BufferedWriter(prifw);
			pribw.write(privateKeyString);
			pribw.flush();
			pribw.close();
			prifw.close();
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
	}

	public static String loadKeyFromFile(String filePath) throws Exception {
		try {
			BufferedReader br = new BufferedReader(new FileReader(filePath));
			String readLine = null;
			StringBuilder sb = new StringBuilder();
			while ((readLine = br.readLine()) != null) {
				sb.append(readLine);
			}
			br.close();
			return sb.toString();
		} catch (IOException e) {
			throw new Exception("数据读取错误");
		} catch (NullPointerException e) {
			throw new Exception("输入流为空");
		}
	}

	public static String sign(String content, String privateKey) {
		try {
			PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(new Base64().decode(privateKey));
			KeyFactory keyf = KeyFactory.getInstance("RSA");
			PrivateKey priKey = keyf.generatePrivate(priPKCS8);
			java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
			signature.initSign(priKey);
			signature.update(content.getBytes());
			byte[] signed = signature.sign();
			return new Base64().encodeToString(signed);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return null;
	}

	public static boolean check(String content, String sign, String publicKey) {
		try {
			KeyFactory keyFactory = KeyFactory.getInstance("RSA");
			byte[] encodedKey = new Base64().decode(publicKey);
			PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

			java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
			signature.initVerify(pubKey);
			signature.update(content.getBytes());

			boolean bverify = signature.verify(new Base64().decode(sign));
			return bverify;

		} catch (Exception e) {
			logger.error(e.getMessage());
		}

		return false;
	}

	public static boolean check(String content, String sign) throws Exception {
		String publicKeyPath = System.getProperty("appHome") + PUBLIC_KEY_PATH;
		String publicKey = loadKeyFromFile(publicKeyPath);
		return check(content, sign, publicKey);
	}

	public static void main(String[] args) {

		String publicKeyPath = "D:\\rsa_key\\publicKeyFile";
		String privateKeyPath = "D:\\rsa_key\\privateKeyFile";

		// 创建秘钥对，实际使用时，只要创建一次，永久使用
		// genKeyPair(privateKeyPath, publicKeyPath);
		// appId=A200001&userId=value1&ip=value2&timestamp=1515587769340
		String content = "appId=A200001&userId=liff&ip=192.168.222.183&timestamp=1515587769340";
		// Rc11ABmvRzKtzLHbaLio9a/cAXGoA77nklBhABaTFJQEJrioJD/wSp8r/ovj6a4LapxtV3EaSGA31/TIBrZZM5CEM2103Bxh8T0tjosbm2DcUY6HnyFTw8meV9j11lvQpSMAGGVRo/1ljkmHLQnTciopUCtK74eM793hFRWG20=
		// Rc11ABmvRzKtzLHbaLio9a/cAXGoA77nklBhABaTFJQEJrioJD/wSp8r/ovj6a4LapxtV3+EaSGA31/TIBrZZM5CEM2103Bxh8T0tjosbm2DcUY6HnyFTw8meV9j11lvQpSMAGGVRo/1ljkmHLQnTciopUCtK74eM793hFRWG20=
		// MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYTrybmF7mK5sNiJxHOWbaWaD+vK3INUyTLLVgmEPBrmNR37Iw2XW67EZRPYfP0upern0Nm5FScG39ris+Q2rMqVnKrNIVb+ZaP0oI1gKqsvNBGZIg4ZgT888L3sMZQVwFWxLSGsDj6tx7KtpsaOTGyatb82mqjoDtJhxiW5XYLQIDAQAB
		try {
			String publicKey = loadKeyFromFile(publicKeyPath);
			String privateKey = loadKeyFromFile(privateKeyPath);

			System.out.println("content\t" + content);
			String s = sign(content, privateKey);
			System.out.println("sign\t" + s);
			boolean c = check(content, s, publicKey);
			System.out.println("check\t" + c);

		} catch (Exception e) {
			e.printStackTrace();
			// System.out.println(e.getMessage());
		}

	}

}
